#include "protocol.h"
#include <QDebug>
#include <QFile>
#include <QXmlStreamWriter>
#include <QXmlStreamReader>

Protocol::Protocol(QObject *parent) : QObject(parent)
{

}

bool Protocol::load(const QString _strFileName)
{
    QString fileName = m_strFileName;
    if(!_strFileName.isEmpty())
    {
        fileName = _strFileName;
    }

    if(fileName.isEmpty())
    {
        return false;
    }

    m_strFileName = fileName;

    // 从文件中读取协议数据
    QFile file(fileName);
    if(!file.open(QIODevice::ReadOnly|QIODevice::Text))
    {
        return false;
    }

    m_ProtocolList.clear();
    QXmlStreamReader stream(&file);
    ProtocolItem item;
    while(!stream.atEnd())
    {
        stream.readNext();

        if(stream.name() == "Protocol")
        {
            if(stream.isStartElement())
            {
                m_strAuthor = stream.attributes().value("author").toString();
                m_strName = stream.attributes().value("name").toString();
                m_strVersion = stream.attributes().value("version").toString();
                m_lastEditTime = QDateTime::fromString( stream.attributes().value("lastEditTime").toString());
            }
            else if(stream.isEndElement())
            {

            }
            else
            {

            }

        }
        else if(stream.name() == "ProcotolItem")
        {
            if(stream.isStartElement())
            {
                item = ProtocolItem();

                item.strName = stream.attributes().value("name").toString();
                item.strNote = stream.attributes().value("note").toString();
                item.iCode = stream.attributes().value("code").toInt();
                item.bArray = (stream.attributes().value("isArray").toString()=="true");
                item.iArrayCount = stream.attributes().value("arrayCount").toInt();
                item.bPrivate = (stream.attributes().value("isPrivate").toString() == "true");
                item.access = Global::instance()->stringToAccess( stream.attributes().value("access").toString());
            }
            else if(stream.isEndElement())
            {
                m_ProtocolList.append(item);
            }
        }
        else if(stream.name() == "Param")
        {
            if(stream.isStartElement())
            {
                struParamItem param;
                param.strName = stream.attributes().value("name").toString();
                param.strNote = stream.attributes().value("note").toString();
                param.type = Global::instance()->stringToParamType(stream.attributes().value("type").toString());

                item.paramList.append(param);
            }
            else if(stream.isEndElement())
            {

            }

        }
    }

    return  true;
}

bool Protocol::save(const QString _strFileName)
{
    QString fileName = m_strFileName;
    if(!_strFileName.isEmpty())
    {
        fileName = _strFileName;
    }

    if(fileName.isEmpty())
    {
        return false;
    }

    // 将数据保存到文件中
    QFile file(fileName);
    if(!file.open(QIODevice::WriteOnly|QIODevice::Text))
    {
        return false;
    }

    m_lastEditTime = QDateTime::currentDateTime();

    QXmlStreamWriter stream(&file);

    stream.setAutoFormatting(true);
    stream.writeStartDocument("1.0");
    stream.writeStartElement("Protocol");
    stream.writeAttribute("name", m_strName);
    stream.writeAttribute("version", strVersion());
    stream.writeAttribute("author", m_strAuthor);
    stream.writeAttribute("lastEditTime", m_lastEditTime.toString("yyyy-MM-dd hh:mm:ss"));

    for(int i=0; i<m_ProtocolList.count(); i++)
    {
        saveProtocolItem(stream, m_ProtocolList.at(i));
    }

    stream.writeEndElement();
    stream.writeEndDocument();

    file.close();
    return true;
}

QString Protocol::strFileName() const
{
    return m_strFileName;
}

void Protocol::setStrFileName(const QString &strFileName)
{
    m_strFileName = strFileName;
}

QString Protocol::strVersion() const
{
    return m_strVersion;
}

void Protocol::setStrVersion(const QString &strVersion)
{
    m_strVersion = strVersion;
}

QList<struProtocolItem> Protocol::ProtocolList() const
{
    return m_ProtocolList;
}

void Protocol::setProtocolList(const QList<struProtocolItem> &ProtocolList)
{
    m_ProtocolList = ProtocolList;
}

struProtocolItem Protocol::itemAt(int n)
{
    return m_ProtocolList.at(n);
}

void Protocol::removeItem(int n)
{
    m_ProtocolList.removeAt(n);
}

int Protocol::itemCount()
{
    return  m_ProtocolList.count();
}

void Protocol::addItem(const struProtocolItem item)
{
    m_ProtocolList.append(item);
}

void Protocol::setItem(int n, const struProtocolItem item)
{
    if((n>=0)&& (n<itemCount()))
    {
        m_ProtocolList[n] = item;
    }
}

QString Protocol::strAuthor() const
{
    return m_strAuthor;
}

void Protocol::setStrAuthor(const QString &strAuthor)
{
    m_strAuthor = strAuthor;
}

QDateTime Protocol::lastEditTime() const
{
    return m_lastEditTime;
}

QString Protocol::strName() const
{
    return m_strName;
}

void Protocol::setStrName(const QString &strName)
{
    m_strName = strName;
}

// 存储协议Item
void Protocol::saveProtocolItem(QXmlStreamWriter &stream, struProtocolItem protocolItem)
{
    stream.writeStartElement("ProcotolItem");

    stream.writeAttribute("name", protocolItem.strName);
    stream.writeAttribute("note", protocolItem.strNote);
    stream.writeAttribute("code", QString::number( protocolItem.iCode));
    stream.writeAttribute("isArray", protocolItem.bArray?"true":"false");
    stream.writeAttribute("arrayCount", QString::number(protocolItem.iArrayCount));
    stream.writeAttribute("isPrivate", protocolItem.bPrivate?"true":"false");
    stream.writeAttribute("access", Global::instance()->accessToString(protocolItem.access));

    for(int i=0; i<protocolItem.paramList.count(); i++)
    {
        saveParamItem(stream, protocolItem.paramList.at(i));
    }

    stream.writeEndElement();

}

// 存储参数Item
void Protocol::saveParamItem(QXmlStreamWriter &stream, struParamItem param)
{
    stream.writeStartElement("Param");

    stream.writeAttribute("name", param.strName);
    stream.writeAttribute("note", param.strNote);
    stream.writeAttribute("type", Global::instance()->paramTypeToString(param.type));

    stream.writeEndElement();
}
